import * as moment from 'moment';

export class DayViewCalendar {
    private _container: HTMLLIElement;
    private _innerTasks: TaskCell[] = [];
    private _dataSource: any[];
    private _option: DayViewOptions;

    private _dayTaskRender: DayTaskRender;
    private _dayCellRender: DayCellRender;
    private _dayTimeColumnRender: DayTimeColumnRender;

    get innerTasks(): TaskCell[] {
        return this._innerTasks;
    }

    get dayCellRender(): DayCellRender {
        return this._dayCellRender;
    }

    get dayTaskRender(): DayTaskRender {
        return this._dayTaskRender;
    }

    get container(): HTMLLIElement {
        return this._container;
    }
    get option(): DayViewOptions {
        return this._option;
    }

    /**
     *
     */
    constructor(ele: Element | any, option: DayViewOptions | any) {
        this._container = ele;
        this._dataSource = [];
        const angularCssAtr = ele.getAttributeNames()[0];
        const innerOption = this.defaultDayViewOptions(angularCssAtr) as any;
        if (option != null) {
            for (const key in innerOption) {
                const val = option[key];
                if (val) {
                    innerOption[key] = val;
                }
            }
        }

        if (!innerOption.dayCellRender) {
            const dtr = new DefaultDayCellRender(
                innerOption.dayCellWidth,
                innerOption.dayCellHeight,
                angularCssAtr
            );
            innerOption.dayCellRender = dtr;
        }

        if (!innerOption.dayTaskRender) {
            const dcr = new DefaultDayTaskRender(innerOption.dayCellRender);
            innerOption.dayTaskRender = dcr;
        }

        if (!innerOption.dayTimeColumnRender) {
            const dtir = new DefaultDayTimeColumnRender(
                innerOption.dayCellRender
            );
            innerOption.dayTimeColumnRender = dtir;
        }

        console.log(innerOption);
        this._dayTaskRender = innerOption.dayTaskRender;
        this._dayCellRender = innerOption.dayCellRender;
        this._dayTimeColumnRender = innerOption.dayTimeColumnRender;
        this._option = innerOption;
    }

    private defaultDayViewOptions(angularCssAtr: string): DayViewOptions {
        const defWidht = 160;
        const defHeight = 100;

        return {
            dayStartTime: moment(moment().format('yyyy-MM-DD 08:00')).toDate(),
            dayEndTime: moment(moment().format('yyyy-MM-DD 20:00')).toDate(),
            daySpacing: 60,
            dayRangeSpacing: 10,
            dayCellHeight: defHeight,
            dayCellWidth: defWidht,
        } as unknown as DayViewOptions;
    }

    initDataSource(data: DayTaskData[]) {
        const start = moment(this._option.dayStartTime);
        const end = moment(this._option.dayEndTime);
        const spacing = this._option.daySpacing;
        const arr = [];

        for (let index = start; ; ) {
            if (index <= end) {
                const st = index.toDate();

                index = index.add(spacing, 'minutes');
                const ed = index.toDate();
                let fdata = data.filter(
                    (_) => _.startTime >= st && _.startTime <= ed
                );
                fdata = fdata.sort((a, b) => {
                    return a.startTime.getTime() - b.startTime.getTime();
                });

                arr.push({
                    startTime: st,
                    endTime: ed,
                    rangeTimeData: fdata,
                });
                continue;
            }
            const st = index.toDate();
            const ed = end.toDate();
            let fdata =
                data.filter((_) => _.startTime >= st && _.endTime <= ed) || [];
            fdata = fdata.sort((a, b) => {
                return a.startTime.getTime() - b.startTime.getTime();
            });
            arr.push({
                startTime: st,
                endTime: ed,
                rangeTimeData: fdata,
            });
            break;
        }
        this._dataSource = arr;
    }

    createDomContext() {}

    render(data: DayTaskData[]): void {
        this.initDataSource(data);
        console.log(this._dataSource);
        const rangeSpacing = this._option.dayRangeSpacing;
        const dayTimeColumnDom = this._dayTimeColumnRender.render(
            this._option.dayStartTime,
            this._option.dayEndTime,
            this._option.daySpacing
        );
        const dataList = this._dataSource;
        const taskContainer = document.createElement('div');
        for (let i = 0; i < dataList.length; i++) {
            const rowInfo = dataList[i];
            const mins = Math.abs(
                moment(rowInfo.startTime).diff(
                    moment(rowInfo.endTime),
                    'minutes'
                )
            );
            let len =
                mins % rangeSpacing == 0
                    ? mins / rangeSpacing
                    : Math.ceil(mins / rangeSpacing);

            const row = this._dayCellRender.createRow();
            //const rowTask = this._dayCellRender.createRow();
            if (len < rowInfo.rangeTimeData.length) {
                len = rowInfo.rangeTimeData.length;
            }

            for (let j = 0; j < len; j++) {
                const uData = rowInfo.rangeTimeData[j];
                const cell = new TaskCell(
                    this,
                    i,
                    j,
                    uData?.canDrop,
                    uData?.canRemove,
                    uData
                );

                this._innerTasks.push(cell);

                row.appendChild(cell._container);
                cell.renderInit();
            }

            taskContainer.appendChild(row);
        }
        this._container.appendChild(dayTimeColumnDom);
        this._container.appendChild(taskContainer);
        this._container.onscroll = (e: any) => {
            dayTimeColumnDom.style.left = e.target.scrollLeft + 'px';
        };
    }
}

export class TaskCell {
    public _container: HTMLElement;
    public _textcontainer!: HTMLElement | undefined;
    private _row: number;
    private _col: number;

    get container(): HTMLElement {
        return this._container;
    }

    get row(): number {
        return this._row;
    }
    get col(): number {
        return this._col;
    }
    get textcontainer(): HTMLElement | undefined {
        return this._textcontainer;
    }

    get hasText(): boolean {
        return this._data != null;
    }
    get width(): number | undefined {
        return this._width;
    }
    get height(): number | undefined {
        return this._height;
    }
    private _minDistance: number = 5;
    private _distance: number = 0;
    private _isStartDrop: boolean = false;
    private _cloneTextContainer!: HTMLElement;
    private _toTaskCell!: TaskCell;
    private _events: any[] = [];
    private _dayView!: DayViewCalendar;
    private _data!: any;
    private _width?: number;
    private _height?: number;
    private _option!: DayCellOptions;
    private _dayTaskRender?: DayTaskRender;
    private _dayCellRender?: DayCellRender;
    private _canDrop: boolean = false;
    private _canClose: boolean = false;

    constructor(
        dayView: DayViewCalendar,
        row: number,
        col: number,
        _canDrop: boolean,
        _canClose: boolean,
        data: any
    ) {
        this._row = row;
        this._col = col;

        const options = dayView.option;
        this._width = options.dayCellWidth;
        this._height = options.dayCellHeight;
        this._dayTaskRender = options.dayTaskRender;
        this._dayCellRender = options.dayCellRender;
        this._dayView = dayView;
        this._data = data?.data;
        this._canDrop = _canDrop;
        this._canClose = _canClose;

        this._container = this._dayCellRender?.createCell() as any;
    }

    renderInit() {
        this.render(null, false, false);
    }

    render(data: any, canDrop: boolean, canClose: boolean) {
        if (data) {
            this._data = data;
            this._canDrop = canDrop;
            this._canClose = canClose;
        }
        if (this._data) {
            const domfrontDropOld = this.textcontainer as any;
            this.removeEvent(domfrontDropOld, 'mousedown', this.mouseDown);
            domfrontDropOld?.remove();
            const baseDom = this._dayTaskRender?.createBase() as any;
            const viewEmpty = this._dayTaskRender?.getViewEmpty() as any;
            this._dayTaskRender?.renderViewData(baseDom, viewEmpty, this._data);
            this.container.appendChild(baseDom);

            const domfrontDrop = baseDom as any;
            this._textcontainer = baseDom;
            if (this._canClose) {
                domfrontDrop.appendChild(this.createCloseTextBtn());
            }
            if (this._canDrop) {
                const domfrontDrop = this.textcontainer as any;
                this.addEvent(domfrontDrop, 'mousedown', this.mouseDown);
            }
        } else {
        }
    }

    createCloseTextBtn() {
        const div = this._dayTaskRender?.createCloseBtn() as any;

        this.addEvent(div, 'click', this.onCloseClick);
        return div;
    }

    onCloseClick(e: any) {
        e.preventDefault();
        e.stopPropagation();

        const res = this._option?.onTaskRemove(this._data);
        if (res) {
            this._textcontainer?.remove();
            (this._textcontainer as any) = null;
            this._data = null;
        }
    }

    addEvent(dom: HTMLElement, eName: string, methodTarget: any) {
        let findEvent = this._events.find(
            (_) => _.dom == dom && _.eName == eName
        );
        if (findEvent == null) {
            findEvent = {
                dom: dom,
                eName: eName,
            };
            this._events.push(findEvent);
        } else {
            this.removeEvent(
                findEvent.dom as any,
                findEvent.eName,
                findEvent.methodTarget as any
            );
        }
        const method = methodTarget.bind(this);
        dom.addEventListener(eName, method);
        findEvent.methodTarget = method;
    }
    removeEvent(dom: HTMLElement, eName: string, methodTarget: any) {
        if (!dom) {
            return;
        }
        const findEvent = this._events.find(
            (_) => _.dom == dom && _.eName == eName
        );
        dom.removeEventListener(eName, findEvent.methodTarget);
    }

    mouseDown(e: MouseEvent) {
        e.preventDefault();
        e.stopPropagation();
        this.addEvent(document.body, 'mousemove', this.mouseMove);
        this.addEvent(document.body, 'mouseup', this.mouseUp);
    }

    mouseMove(e: MouseEvent) {
        e.preventDefault();
        e.stopPropagation();
        if (this._distance <= this._minDistance) {
            this._distance++;
            return;
        }

        if (!this._isStartDrop) {
            this._isStartDrop = true;
            const style = this._textcontainer?.style;
            if (style != null) {
                style.opacity = '0.3';
            }
            const cloneDom = this._textcontainer?.cloneNode(true) as any;
            cloneDom.style.opacity = '0.8';
            cloneDom.style.zIndex = 999;
            this._cloneTextContainer = cloneDom;
            this.container.appendChild(cloneDom);
        }
        const toCell = MoveUtils.getDropInTaskCell(
            e,
            this._dayView.innerTasks,
            this._dayView.container
        );

        if (toCell == null) {
            return;
        }
        // if (toCell.row != this.row) {
        //     return;
        // }
        MoveUtils.setMovedTaskCell(this._cloneTextContainer, this, toCell, {
            width: this._width,
            height: this._height,
        });
        this._toTaskCell = toCell;
    }

    mouseUp(e: MouseEvent) {
        e.preventDefault();
        e.stopPropagation();
        this._distance = 0;
        this.removeEvent(document.body, 'mousemove', this.mouseMove);
        this.removeEvent(document.body, 'mouseup', this.mouseUp);
        document.body.onmousemove = null;
        document.body.onmouseup = null;
        if (!this._isStartDrop) {
            return;
        }
        this._isStartDrop = false;
        this._cloneTextContainer.remove();
        (this._cloneTextContainer as any) = null;
        if (this._toTaskCell == null) {
            return;
        }
        if (this._toTaskCell.hasText) {
            if (this._toTaskCell != this) {
                alert('已有任务!');
            }

            const style = this._textcontainer?.style;
            if (style != null) {
                style.opacity = '1';
            }
            return;
        }
        this.removeEvent(
            this._textcontainer as any,
            'mousedown',
            this.mouseDown
        );
        this._textcontainer?.remove();
        this._textcontainer = undefined;

        this._toTaskCell.render(this._data, this._canDrop, this._canClose);
        this._data = null;
    }
}

export class DropDomWrapper {
    private _moveToCalendar!: DayViewCalendar;
    private _originalDom: HTMLElement;
    private _minDistance: number = 5;
    private _distance: number = 0;
    private _isStartDrop: boolean = false;
    private _cloneDom!: HTMLElement;
    private _downPoint!: MouseEvent;
    private _events: any[] = [];
    private _toTaskCell!: TaskCell;
    private _moveToDom!: HTMLElement;
    private _moveFirstIntoDom!: TaskCell;
    private _data: any;
    /**
     *
     */
    constructor(
        ele: HTMLElement | any,
        moveToCalendar: DayViewCalendar,
        data: any
    ) {
        this._originalDom = ele;
        this._moveToCalendar = moveToCalendar;
        this._data = data;
        this.addEvent(this._originalDom, 'mousedown', this.mouseDown);
    }

    addEvent(dom: HTMLElement, eName: string, methodTarget: any) {
        let findEvent = this._events.find(
            (_) => _.dom == dom && _.eName == eName
        );
        if (findEvent == null) {
            findEvent = {
                dom: dom,
                eName: eName,
            };
            this._events.push(findEvent);
        } else {
            this.removeEvent(
                findEvent.dom as any,
                findEvent.eName,
                findEvent.methodTarget as any
            );
        }
        const method = methodTarget.bind(this);
        dom.addEventListener(eName, method);
        findEvent.methodTarget = method;
    }
    removeEvent(dom: HTMLElement, eName: string, methodTarget: any) {
        if (!dom) {
            return;
        }
        const findEvent = this._events.find(
            (_) => _.dom == dom && _.eName == eName
        );
        dom.removeEventListener(eName, findEvent.methodTarget);
    }

    mouseDown(e: MouseEvent) {
        e.preventDefault();
        e.stopPropagation();

        this._downPoint = e;

        this.addEvent(window.document.body, 'mousemove', this.mouseMove);
        this.addEvent(window.document.body, 'mouseup', this.mouseUp);
    }

    mouseMove(e: MouseEvent) {
        e.preventDefault();
        e.stopPropagation();
        if (this._distance <= this._minDistance) {
            this._distance++;
            return;
        }

        if (!this._isStartDrop) {
            this._isStartDrop = true;

            this._cloneDom = this._originalDom.cloneNode(true) as any;
            this._cloneDom.style.position = 'absolute';

            this._cloneDom.style.zIndex = '99999';
            this._originalDom.style.opacity = '0.5';
            window.document.body.appendChild(this._cloneDom);
        }
        let left = e.clientX - this._downPoint.offsetX;
        let top = e.clientY - this._downPoint.offsetY;
        this._cloneDom.style.top = top + 'px';
        this._cloneDom.style.left = left + 'px';
        if (
            !MoveUtils.isMouseDropInDiv(e, this._moveToCalendar.container, null)
        ) {
            this._cloneDom.style.backgroundColor = 'black';
            this._cloneDom.style.display = 'flex';
            if (this._moveToDom) {
                this._moveToDom.style.display = 'none';
            }
        } else {
            this._cloneDom.style.backgroundColor = 'green';
            this._cloneDom.style.display = 'none';
            if (!this._moveToDom) {
                const dom = this._moveToCalendar.dayTaskRender.createBase();
                dom.appendChild(
                    this._moveToCalendar.dayTaskRender.getViewEmpty()
                );
                this._moveToDom = dom;

                this._moveToDom.style.zIndex = '9999';
            }
            this._moveToDom.style.display = 'flex';

            const toCell = MoveUtils.getDropInTaskCell(
                e,
                this._moveToCalendar.innerTasks,
                this._moveToCalendar.container
            );

            if (toCell == null) {
                return;
            }
            if (!this._moveFirstIntoDom) {
                this._moveFirstIntoDom = toCell;

                toCell._container.appendChild(this._moveToDom);
            }
            console.log(toCell.col, toCell.row);
            MoveUtils.setMovedTaskCell(
                this._moveToDom,
                this._moveFirstIntoDom,
                toCell,
                {
                    width: this._moveFirstIntoDom.width,
                    height: this._moveFirstIntoDom.height,
                }
            );
            this._toTaskCell = toCell;
        }
    }

    mouseUp(e: MouseEvent) {
        e.preventDefault();
        e.stopPropagation();
        this.removeEvent(window.document.body, 'mousemove', this.mouseMove);
        this.removeEvent(window.document.body, 'mouseup', this.mouseUp);
        if (!this._isStartDrop) {
            return;
        }
        this._isStartDrop = false;
        if (this._cloneDom) {
            this._cloneDom.remove();
            (this._cloneDom as any) = null;
        }
        if (this._moveFirstIntoDom) {
            (this._moveFirstIntoDom as any) = null;
        }

        let isDropIn = false;
        if (this._moveToDom) {
            isDropIn = this._moveToDom.style.display != 'none';
            this._moveToDom.remove();
            (this._moveToDom as any) = null;
        }
        this._originalDom.style.opacity = '1';
        if (isDropIn) {
            if (this._toTaskCell.hasText) {
                alert('已有任务!');
                return;
            }
            this._toTaskCell.render(this._data, true, true);
            this._originalDom.remove();
        }
    }
}

class MoveUtils {
    public static isMouseDropInDiv(
        event: MouseEvent,
        ele: HTMLElement,
        scrollPage: HTMLElement | null
    ): boolean {
        const sx = scrollPage?.scrollLeft ?? 0;
        const sy = scrollPage?.scrollTop ?? 0;
        const x = event.pageX + sx;
        const y = event.pageY + sy;

        const div = ele;
        const ofs = div.getBoundingClientRect();
        const y1 = ofs.top + sy; //div上面两个的点的y值
        const y2 = y1 + div.clientHeight; //div下面两个点的y值
        const x1 = ofs.left + sx; //div左边两个的点的x值
        const x2 = x1 + div.clientWidth; //div右边两个点的x的值
        if (x < x1 || x > x2 || y < y1 || y > y2) {
            return false;
        } else {
            return true;
        }
    }

    static setMovedTaskCell(
        ele: HTMLElement,
        fromCell: TaskCell,
        toCell: TaskCell,
        option: any
    ) {
        console.log(option.height, option.width);
        const xrows = toCell.row - fromCell.row;
        const top = xrows * option.height + xrows * 2 + 'px';
        const xcols = toCell.col - fromCell.col;
        const left = xcols * option.width + xcols * 2 + 'px';
        ele.style.top = top;
        ele.style.left = left;
    }

    static getDropInTaskCell(
        event: MouseEvent,
        taskCells: TaskCell[],
        scrollPage: HTMLElement
    ): TaskCell | null {
        const doms = taskCells;
        for (const dom of doms) {
            if (MoveUtils.isMouseDropInDiv(event, dom._container, scrollPage)) {
                return dom;
            }
        }
        return null;
    }
}

abstract class AngularDomRender {
    _angularCssAtr!: string;

    /**
     *
     */
    constructor(angularCssAtr: string) {
        this._angularCssAtr = angularCssAtr;
    }

    createElement(tagName: string = 'div'): HTMLElement {
        const dom = document.createElement(tagName);
        dom.setAttribute(this._angularCssAtr, '');
        return dom;
    }
    setDomWidthAndHeight(dom: HTMLElement, width: string, height: string) {
        dom.style.minWidth = width;
        dom.style.width = width;
        dom.style.height = height;
        dom.style.minHeight = height;
    }
}
class DefaultDayCellRender extends AngularDomRender implements DayCellRender {
    readonly dayCellWidth: number;
    readonly dayCellHeight: number;

    /**
     *
     */
    constructor(
        dayCellWidth: number,
        dayCellHeight: number,
        angularCssAtr: string
    ) {
        super(angularCssAtr);
        this.dayCellHeight = dayCellHeight;
        this.dayCellWidth = dayCellWidth;
    }
    createCell(): HTMLElement {
        return this.createTaskContainer();
    }
    createRow(): HTMLElement {
        const dom = this.createElement();
        dom.className = 'row';
        return dom;
    }

    createRowContainer(): HTMLElement {
        const dom = this.createElement();
        dom.className = 'row-task';
        return dom;
    }

    private createTaskContainer(): HTMLElement {
        const dom = this.createElement();
        dom.className = 'task-cell';
        this.setDomWidthAndHeight(
            dom,
            this.dayCellWidth + 'px',
            this.dayCellHeight + 'px'
        );
        const domBack = this.createElement();
        domBack.className = 'cell-back';
        this.setDomWidthAndHeight(
            domBack,
            this.dayCellWidth + 'px',
            this.dayCellHeight + 'px'
        );

        dom.appendChild(domBack);
        return dom;
    }
}

class DefaultDayTimeColumnRender
    extends AngularDomRender
    implements DayTimeColumnRender
{
    dayCellRender: DayCellRender;

    /**
     *
     */
    constructor(dayCellRender: DayCellRender) {
        super((dayCellRender as DefaultDayCellRender)._angularCssAtr);
        this.dayCellRender = dayCellRender;
    }

    render(startTime: Date, endTime: Date, spacing: number): HTMLElement {
        const start = moment(startTime);
        const end = moment(endTime);
        const arr = [];

        const pCellHeight = this.dayCellRender.dayCellHeight;
        for (let index = start; ; ) {
            if (index <= end) {
                arr.push(index.format('HH:mm'));
                index = index.add(spacing, 'minutes');
                continue;
            }
            arr.push(end.format('HH:mm'));
            break;
        }
        const taskTimeCol = this.createElement();
        taskTimeCol.style.position = 'relative';
        taskTimeCol.style.float = 'left';
        taskTimeCol.style.display = 'flex';
        taskTimeCol.style.flexDirection = 'column';
        taskTimeCol.style.height = '100%';
        for (const item of arr) {
            const dom = this.createElement();
            dom.className = 'row-time';
            dom.style.height = pCellHeight + 'px';
            dom.style.minHeight = pCellHeight + 'px';

            dom.innerHTML = `<span style='margin-top:2px;display:flex;justify-content: center;'>${item}</span>`;
            taskTimeCol.appendChild(dom);
        }

        return taskTimeCol;
    }
}

class DefaultDayTaskRender extends AngularDomRender implements DayTaskRender {
    dayCellRender: DayCellRender;
    /**
     *
     */
    constructor(dayCellRender: DayCellRender) {
        super((dayCellRender as DefaultDayCellRender)._angularCssAtr);
        this.dayCellRender = dayCellRender;
    }
    createBase(): HTMLElement {
        return this.createTaskContainer();
    }
    getViewEmpty(): HTMLElement {
        const domfront = this.createElement();
        domfront.className = 'cell-front';

        const domfrontleft = this.createElement();
        domfrontleft.className = 'cell-front-left';

        const domfrontright = this.createElement();
        domfrontright.className = 'cell-front-right';

        domfront.appendChild(domfrontleft);
        domfront.appendChild(domfrontright);

        return domfront;
    }
    renderViewData(
        domBase: HTMLElement,
        domEmpty: HTMLElement,
        data: any
    ): void {
        const txtDom = domEmpty.querySelector('.cell-front-right');
        this.createText(txtDom, data);
        domBase.appendChild(domEmpty);
    }

    createCloseBtn(): HTMLElement {
        const div = this.createElement('div');
        div.className = 'cell-close';
        return div;
    }

    createText(dom: Element | null, data: any) {
        const div1 = this.createElement('div');
        div1.style.display = 'flex';
        div1.style.width = 'calc(100% - 10px)';
        div1.style.justifyContent = 'space-between';
        div1.style.maxHeight = '33%';
        const div11 = this.createElement('div');
        div11.innerText = data.no;

        const div12 = this.createElement('div');
        div12.innerText = data.sex;

        const div13 = this.createElement('div');
        div13.innerText = data.age;

        div1.appendChild(div11);
        div1.appendChild(div12);
        div1.appendChild(div13);

        const div2 = this.createElement('div');
        div2.style.display = 'flex';
        div2.style.justifyContent = 'space-between';
        div2.style.maxHeight = '34%';
        const div21 = this.createElement('div');
        div21.innerText = data.name;

        div21.style.fontWeight = '700';
        const div22 = this.createElement('div');
        div22.className = 'task-ok';
        div22.innerText = '✔';
        div2.appendChild(div21);
        div2.appendChild(div22);

        const div3 = this.createElement('div');
        div3.style.display = 'flex';
        div3.style.justifyContent = 'space-between';
        div3.style.maxHeight = '33%';
        const div31 = this.createElement('div');
        div31.innerText = data.pos;

        div31.style.textAlign = 'left';

        const div32 = this.createElement('div');
        div32.innerText = data.current + '/' + data.total;

        div32.style.textAlign = 'right';

        div3.appendChild(div31);
        div3.appendChild(div32);

        dom?.appendChild(div1);
        dom?.appendChild(div2);
        dom?.appendChild(div3);
    }

    private createTaskContainer(): HTMLElement {
        const pCellWidht = this.dayCellRender.dayCellWidth;
        const pCellHeight = this.dayCellRender.dayCellHeight;
        const domfrontDrop = this.createElement();
        domfrontDrop.className = 'cell-front-drop';
        this.setDomWidthAndHeight(
            domfrontDrop,
            pCellWidht + 'px',
            pCellHeight + 'px'
        );
        return domfrontDrop;
    }
}

export interface DayTimeColumnRender {
    render(startTime: Date, endTime: Date, spacing: number): HTMLElement;
}

export interface DayCellRender {
    dayCellHeight: number;
    dayCellWidth: number;
    createCell(): HTMLElement;
    createRow(): HTMLElement;
}

export interface DayTaskRender {
    dayCellRender: DayCellRender;

    createBase(): HTMLElement;
    createCloseBtn(): HTMLElement;
    getViewEmpty(): HTMLElement;
    renderViewData(
        domBase: HTMLElement,
        domEmpty: HTMLElement,
        data: any
    ): void;
}

export interface DayTaskData {
    startTime: Date;
    endTime: Date;
    canDrop: boolean;
    canRemove: boolean;
    data: any;
}

export interface DayViewOptions {
    dayStartTime: Date;
    dayEndTime: Date;
    daySpacing: number;
    dayRangeSpacing: number;
    dayCellHeight?: number;
    dayCellWidth?: number;

    onNewTaskEnter?: Function;
    onTaskMoved?: Function;
    onTaskRemove?: Function;

    dayTaskRender?: DayTaskRender;
    dayCellRender?: DayCellRender;
    dayTimeColumnRender?: DayTimeColumnRender;
}

interface DayCellOptions {
    cellStartTime: Date;
    cellEndTime: Date;

    dayCellHeight: string;
    dayCellWidth: string;

    onNewTaskEnter: Function;
    onTaskMoved: Function;
    onTaskRemove: Function;
}
